#include "cinatra/http_server.hpp"
#include <iostream>

#include "ormpp/dbng.hpp"

using namespace cinatra;

struct log_t {
	bool before(const request &req, response &res)
	{
		std::cout << "before log" << std::endl;
		return true;
	}

	bool after(const request &req, response &res)
	{
		std::cout << "after log" << std::endl;
		return true;
	}
};

struct check {
	bool before(const request &req, response &res)
	{
		/*
		std::cout << "before check" << std::endl;
		if (req.get_header_value("name").empty()) {
			res.set_status_and_content(status_type::bad_request);
			return false;
		}*/

		return true;
	}

	bool after(const request &req, response &res)
	{
		std::cout << "after check" << std::endl;
		return true;
	}
};

int main()
{
    ormpp::dbng<postgresql> pg;
	nanolog::initialize(nanolog::GuaranteedLogger(), "/tmp/", "nanolog", 1);
	const int max_thread_num = std::thread::hardware_concurrency();

	http_server server(max_thread_num);
#ifdef CINATRA_ENABLE_SSL
	server.init_ssl_context(true,
							[](auto, auto) { return "123456"; },
							"server.crt",
							"server.key",
							"dh1024.pem");
	bool r = server.listen("0.0.0.0", "https");
#else
	bool r = server.listen("0.0.0.0", "8089");
#endif
	if (!r) {
		LOG_INFO << "listen failed";
		return -1;
	}

	server.set_base_path("base_path", "/feather");
	server.enable_http_cache(false); // set global cache
	server.set_res_cache_max_age(86400);
	server.set_http_handler<GET, POST>("/",
									   [](request &req, response &res) {
										   res.set_status_and_content(
											   status_type::ok, "hello world");
									   },
									   enable_cache{false});

	server.set_http_handler<GET, POST>(
		"/test", [](request &req, response &res) {
			auto name = req.get_header_value("name");
			if (name.empty()) {
				res.set_status_and_content(status_type::bad_request, "no name");
				return;
			}

			auto id = req.get_query_value("id");
			if (id.empty()) {
				res.set_status_and_content(status_type::bad_request);
				return;
			}

			res.set_status_and_content(status_type::ok, "hello world");
		});

	// aspect
	server.set_http_handler<GET, POST>("/aspect",
									   [](request &req, response &res) {
										   res.set_status_and_content(
											   status_type::ok, "hello world");
									   },
									   check{},
									   log_t{});

	// web socket
	server.set_http_handler<GET, POST>("/ws", [](request &req, response &res) {
		assert(req.get_content_type() == content_type::websocket);
		auto state = req.get_state();
		switch (state) {
		case cinatra::data_proc_state::data_begin: {
			std::cout << "websocket start" << std::endl;
		} break;
		case cinatra::data_proc_state::data_continue: {
			auto part_data = req.get_part_data();
			// echo
			std::string str = std::string(part_data.data(), part_data.length());
			req.get_conn()->send_ws_msg(std::move(str), opcode::text);
			std::cout << part_data.data() << std::endl;
		} break;
		case cinatra::data_proc_state::data_close: {
			std::cout << "websocket close" << std::endl;
		} break;
		case cinatra::data_proc_state::data_error: {
			std::cout << "network error" << std::endl;
		} break;
		}
	});

	server.run();
	return 0;
}
